//
//  AnimationRes.m
//  CandyJump
//
//  Created by Bon Lam on 05/03/2011.
//  Copyright 2011 Peru Republic. All rights reserved.
//

#import "AnimationRes.h"

#import "CCAnimation.h"
#import "CCSpriteFrame.h"
#import "CCSpriteFrameCache.h"
#import "PRFile.h"


#define ANIAMTION_RES_XML_ELEM_TAG_ANIMATION				@"animation"
#define ANIAMTION_RES_XML_ELEM_TAG_FRAME					@"frame"

#define ANIAMTION_RES_XML_ATTR_TAG_NAME						@"name"
#define ANIAMTION_RES_XML_ATTR_TAG_DELAY					@"delay"

//=====================================================================================================================
@implementation AnimationRes

@synthesize animationDictionary;

static AnimationRes *sharedRes = nil;


//<AnimationInfo>
//
//<animation name="animIdle" delay="10000">
//<frame value="xxxxxx.png" />
//</animation>
//
//</AnimationInfo>

#pragma mark -
#pragma mark Singleton Object Functions
//---------------------------------------------------------------------------------------------------------------------
- (id)init
{
	self = [super init];
	if (self == nil)  {return self;}
	
	animationDictionary = [[NSMutableDictionary alloc] init];
	
	return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (void)dealloc
{
	[animationDictionary release]; animationDictionary = nil;
	
	[super dealloc];
}

//---------------------------------------------------------------------------------------------------------------------
+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedRes] retain];
}

//---------------------------------------------------------------------------------------------------------------------
- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (id)retain 
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

//---------------------------------------------------------------------------------------------------------------------
- (void)release
{
    //do nothing
}

//---------------------------------------------------------------------------------------------------------------------
- (id)autorelease
{
    return self;
}

#pragma mark Custom Functions
//---------------------------------------------------------------------------------------------------------------------
+ (AnimationRes *)sharedRes
{
    if (sharedRes == nil) {
        sharedRes = [[super allocWithZone:NULL] init];
    }
    return sharedRes;
}

//---------------------------------------------------------------------------------------------------------------------
- (void)clearCachedAnimation
{
	[animationDictionary release];
	animationDictionary = nil;
}

//	Return an dictionary of CCAnimation
//---------------------------------------------------------------------------------------------------------------------
- (NSMutableDictionary*)loadAnimation:(NSString*)filename
{
	//	Load from cache first, parse xml file if not found
	NSMutableDictionary* requestedAnimation = (NSMutableDictionary*)[animationDictionary objectForKey:filename];
	if (requestedAnimation != nil) {
		return requestedAnimation;	
	}
	
	//	Not found in cache
	//	Init animation array
	if (currentLoadingAnimationDictionary != nil) {
		[currentLoadingAnimationDictionary release];
		currentLoadingAnimationDictionary = nil;
	}
	currentLoadingAnimationDictionary = [[NSMutableDictionary alloc] init];
	
	//	Parse file
	NSString* filePath = [PRFile getFilePath:filename];
	[self parseXMLFile:filePath];
	
	//	Add array to dictionary
	[animationDictionary setObject:currentLoadingAnimationDictionary forKey:filename];
	[currentLoadingAnimationDictionary release];
	currentLoadingAnimationDictionary = nil;
	
	return (NSMutableDictionary*)[animationDictionary objectForKey:filename];
}

#pragma mark NSXMLParserDelegate
//---------------------------------------------------------------------------------------------------------------------
- (BOOL)parseXMLFile:(NSString *)filename
{	
	//  Load Object List XML file
	NSData *xmlData = [NSData dataWithContentsOfFile:filename];
	
	NSAssert(xmlData != nil, @"[AnimationRes parseXMLFile:filename] Error - Unable to load file data: ""%@""");
	
	NSError* error = nil;
	[self parseXMLData:xmlData parseError:&error];
	
	return (error == nil);
}

//---------------------------------------------------------------------------------------------------------------------
- (void)parseXMLData:(NSData *)data parseError:(NSError **)error
{
	NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    [parser setDelegate:self];
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];
    [parser parse];
	
    NSError *parseError = [parser parserError];
    if (parseError && error) {
        *error = parseError;
    }
    [parser release];
}

//---------------------------------------------------------------------------------------------------------------------
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
	NSString* nodeName = [elementName lowercaseString];
	
	if ([nodeName isEqualToString:ANIAMTION_RES_XML_ELEM_TAG_ANIMATION]) {
		
		NSAssert(currentLoadingAnimation == nil, @"[AnimationRes parser:didStartElement:namespaceURI:qualifiedName:] Error - currentLoadingAnimation is not nil");
		
		NSString* animName = [attributeDict valueForKey:ANIAMTION_RES_XML_ATTR_TAG_NAME];
		float delay = [[attributeDict valueForKey:ANIAMTION_RES_XML_ATTR_TAG_DELAY] floatValue];
		
		NSAssert(animName != nil, @"[AnimationRes parser:didStartElement:namespaceURI:qualifiedName:] Error - Unable to load animation name");
		
		currentLoadingAnimation = [[CCAnimation alloc] init];
		[currentLoadingAnimation setName:animName];
		[currentLoadingAnimation setDelay:delay];
		
		[currentLoadingAnimationDictionary setObject:currentLoadingAnimation forKey:animName];
	}
	
	if ([nodeName isEqualToString:ANIAMTION_RES_XML_ELEM_TAG_FRAME]) {
		
		NSString* frameName = [attributeDict valueForKey:ANIAMTION_RES_XML_ATTR_TAG_NAME];
		NSAssert(frameName != nil, @"[AnimationRes parser:didStartElement:namespaceURI:qualifiedName:] Error - Unable to load frame name");
		
		CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frameName];
		NSAssert(frame != nil, @"[AnimationRes parser:didStartElement:namespaceURI:qualifiedName:] Error - Unable to load frame from cache");
		
		[currentLoadingAnimation addFrame:frame];
	}
}

//---------------------------------------------------------------------------------------------------------------------
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
	NSString* nodeName = [elementName lowercaseString];
	
	if ([nodeName isEqualToString:ANIAMTION_RES_XML_ELEM_TAG_ANIMATION]) {
		
		[currentLoadingAnimation release];
		currentLoadingAnimation = nil;
	}
}

//---------------------------------------------------------------------------------------------------------------------
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
	
}

//---------------------------------------------------------------------------------------------------------------------
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
	
}

@end
